package com.atguigu.controller;

import com.atguigu.constant.MqConst;
import com.atguigu.constant.RedisConst;
import com.atguigu.entity.*;
import com.atguigu.feign.OrderFeignClient;
import com.atguigu.feign.UserFeignClient;
import com.atguigu.result.RetVal;
import com.atguigu.result.RetValCodeEnum;
import com.atguigu.service.SeckillProductService;
import com.atguigu.util.AuthContextHolder;
import com.atguigu.util.MD5;
import com.atguigu.utils.DateUtil;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author ：Hachimen
 * @date ：Created in 2021/9/14 16:22
 * @description：
 * @modified By：
 * @version:
 */
@RestController
@RequestMapping("/seckill")
public class SeckillController {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillProductService seckillProductService;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private UserFeignClient userFeignClient;
    @Autowired
    private OrderFeignClient orderFeignClient;

    //1.查询所有秒杀商品
    @GetMapping("/queryAllSeckillProduct")
    public RetVal queryAllSeckillProduct() {
        List<SeckillProduct> seckillProductList = redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).values();
        return RetVal.ok(seckillProductList);
    }


    //2.根据skuId 获取秒杀对象数据
    @GetMapping("/getSeckillProductBySkuId/{skuId}")
    public RetVal getSeckillProductBySkuId(@PathVariable Long skuId) {
        SeckillProduct seckillProduct = seckillProductService.getSeckillProductBySkuId(skuId);
        return RetVal.ok(seckillProduct);
    }

    //3.生成下单码
    @GetMapping("/generateSeckillCode/{skuId}")
    public RetVal generateSeckillCode(@PathVariable Long skuId, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        if (!StringUtils.isEmpty(userId)) {
            //从缓存中查询秒杀商品
            SeckillProduct seckillProduct = (SeckillProduct) redisTemplate.boundHashOps(RedisConst.SECKILL_PRODUCT).get(skuId+"");
            //判断是否在秒杀时间范围内
            if (DateUtil.dateCompare(seckillProduct.getStartTime(), new Date()) && DateUtil.dateCompare(new Date(), seckillProduct.getEndTime())) {
                //生成规则 将用户Id使用md5加密
                String seckillCode = MD5.encrypt(userId);
                return RetVal.ok(seckillCode);
            }
        }

        return RetVal.fail().message("获取下单码失败");
    }


    //4.秒杀预下单
    @PostMapping("/prepareSeckill/{skuId}")
    public RetVal prepareSeckill(@PathVariable Long skuId, String seckillCode, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //a.抢购码是否匹配

        if (!MD5.encrypt(userId).equals(seckillCode)) {
            //抢购码不匹配的时候报异常
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //没有获取到状态位信息时
        String state = (String) redisTemplate.opsForValue().get(RedisConst.SECKILL_STATE_PREFIX + skuId);
        if (StringUtils.isEmpty(state)) {
            return RetVal.build(null, RetValCodeEnum.SECKILL_ILLEGAL);
        }
        //b.该商品是否可以秒杀 状态位是正常(1)
        if (RedisConst.CAN_SECKILL.equals(state)) {
            //可以秒杀
            UserSeckillSkuInfo userSeckillSkuInfo = new UserSeckillSkuInfo();
            userSeckillSkuInfo.setSkuId(skuId);
            userSeckillSkuInfo.setUserId(userId);
            rabbitTemplate.convertAndSend(MqConst.PREPARE_SECKILL_EXCHANGE, MqConst.PREPARE_SECKILL_ROUTE_KEY, userSeckillSkuInfo);
            //c.把秒杀用户id和商品skuId发送消息给rabbitmq(排队)
        } else {
            //不可以秒杀 已售完
            return RetVal.build(null, RetValCodeEnum.SECKILL_FINISH);
        }
        return RetVal.ok();
    }

    //5.是否具有抢单的资格
    @GetMapping(value = "/hasQualified/{skuId}")
    public RetVal hasQualified(@PathVariable Long skuId, HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);

        return seckillProductService.hasQualified(userId, skuId);
    }

    //6.秒杀商品确认信息
    @GetMapping("/seckillConfirm")
    public RetVal seckillConfirm(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //获取秒杀到的商品订单信息
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if(prepareSeckillOrder == null){
            return RetVal.fail().message("非法操作");
        }
        //获取收货地址
        List<UserAddress> userAddresses = userFeignClient.queryAddressByUserId(userId);
        SeckillProduct seckillProduct = prepareSeckillOrder.getSeckillProduct();
        //创建订单详情
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setSkuNum(prepareSeckillOrder.getBuyNum()+"");
        orderDetail.setSkuName(seckillProduct.getSkuName());
        orderDetail.setOrderPrice(seckillProduct.getCostPrice());
        orderDetail.setSkuId(seckillProduct.getSkuId());
        orderDetail.setImgUrl(seckillProduct.getSkuDefaultImg());
        List<OrderDetail> orderDetailList = new ArrayList<>();
        orderDetailList.add(orderDetail);
        Map<String , Object> ret = new HashMap<>();
        ret.put("userAddressList",userAddresses);
        ret.put("orderDetailList",orderDetailList);
        ret.put("totalMoney",seckillProduct.getCostPrice());
        return RetVal.ok(ret);
    }
    //保存秒杀订单
    @PostMapping("/submitSecKillOrder")
    public RetVal submitSecKillOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        //判断用户是否有预下单
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));
        PrepareSeckillOrder prepareSeckillOrder = (PrepareSeckillOrder) redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).get(userId);
        if(prepareSeckillOrder == null){
            return RetVal.fail().message("非法操作");
        }
        //远程调用保存秒杀订单
        Long orderId = orderFeignClient.saveSeckillOrder(orderInfo);
        if(orderId == null){
            return RetVal.fail().message("下单失败");
        }
        //根据userId删除预订单
        redisTemplate.boundHashOps(RedisConst.PREPARE_SECKILL_USERID_ORDER).delete(userId);
        //为了让用户只能购买一次 将秒杀的商品数据保存到缓存
        redisTemplate.boundHashOps(RedisConst.BOUGHT_SECKILL_USER_ORDER).put(userId,orderId.toString());
        return RetVal.ok(orderId);
    }
}
